home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / Tool Chest / Devices / Qwertytunes / BigEasyDialogs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-03  |  12.5 KB  |  601 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        BigEasyDialogs.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Written by:    xxx put writers here xxx
  7.  
  8.     Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <4>      1/7/93    dvb        Improve number-dialog with +/- keys. Make it compile under mpw.
  13.          <3>     4/13/92    dvb        Allow windows to idle behind dialogue. Pass activate/deactivates
  14.                                     to back windows.
  15.          <2>      4/3/92    dvb        New calls for getting text & numbers.
  16.          <1>     1/20/92    dvb        first checked in
  17.  
  18. */
  19.  
  20. /* file: BigEasyDialogs.c
  21.  *
  22.  * Started 2 Jan 1992, more or less.
  23.  *
  24.  */
  25.  
  26.  
  27. /*--------------------------
  28.     Inclusions
  29. --------------------------*/
  30.  
  31. #include <Windows.h>
  32. #include <Dialogs.h>
  33. #include <Controls.h>
  34. #include <OSUtils.h>
  35. #include <ToolUtils.h>
  36. #include <Resources.h>
  37. #include <TextEdit.h>
  38. #include <Memory.h>
  39. #include <Packages.h>
  40.  
  41. #include "IconUtilsPriv.h"
  42. #include "BigEasyDialogs.h"
  43. #include "BigEasy2.h"
  44.  
  45. /*--------------------------
  46.     Constants
  47. --------------------------*/
  48.  
  49. #define kButtonHeight 20
  50. #define kButtonWindowMargin 10
  51. #define kButtonTextMargin 20
  52.  
  53. #define    kOSEvent app4Evt            /* event used by MultiFinder */
  54. #define    kSuspendResumeMessage 1        /* high byte of suspend/resume event message */
  55.  
  56. /*--------------------------
  57.     Local Data
  58. --------------------------*/
  59.  
  60. typedef struct
  61.     {
  62.     StringPtr header;
  63.     StringPtr body;
  64.     short iconID;
  65.     } EasyDialogMessageStuff;
  66.  
  67.  
  68. static EasyDialogButtonList dOkayCancelButtonList =
  69.     {
  70.     2,0,1,
  71.     "\pOkay",0,
  72.     "\pCancel",0
  73.     };
  74.  
  75. static EasyDialogButtonList dSaveDiscardCancelButtonList =
  76.     {
  77.     3,0,2,
  78.     "\pSave",0,
  79.     "\pDiscard",'D',
  80.     "\pCancel",0
  81.     };
  82.  
  83. static Boolean gNumbers = false;        /* true if we're getting a number string */
  84.  
  85. /*--------------------------
  86.     Local Prototypes
  87. --------------------------*/
  88.  
  89. static void EasyDialogMessageUpdateProc(long refcon,const Rect *updateRect);
  90. static void BlinkButton(ControlHandle buttonControl);
  91. static void BlinkItem(DialogPtr theDialog,short item);
  92. static pascal Boolean MyModalFilterProc(DialogPtr theDialog,
  93.         EventRecord *theEvent, short *itemHit);
  94.  
  95. /*--------------------------
  96.     Roughage
  97. --------------------------*/
  98.  
  99. long EasyDialog(Rect *windowRect,
  100.         beDialogUpdate updateProc,
  101.         beDialogKey keyProc,
  102.         beDialogClick clickProc,
  103.         beDialogIdle idleProc,
  104.         EasyDialogButtonList *buttonList,
  105.         long refcon)
  106.     {
  107.     WindowPtr w;
  108.     Rect r,s,updateRect;
  109.     short i;
  110.     short biggestButton,x;
  111.     ControlHandle ch[20];
  112.     Rect defaultButtonRect;
  113.     EventRecord er;
  114.     Boolean done;
  115.     long saveMenus;
  116.     long result;
  117.     long eventCount;
  118.     #pragma unused (clickProc)
  119.  
  120.     HiliteMenu(0);
  121.     r = *windowRect;
  122.  
  123.     if(r.left <= 0)
  124.         {
  125.         s = qd.screenBits.bounds;
  126.  
  127.         OffsetRect(&r,
  128.                 (s.left + s.right - r.left - r.right)/2,
  129.                 (s.top + s.bottom - r.top - r.bottom)/2);
  130.         }
  131.  
  132.     saveMenus = DisableAllMenus();
  133.  
  134.     i = gSystemVersion > 0x700 ? movableDBoxProc : dBoxProc;
  135.  
  136.     if(gHasColor)
  137.         w = NewCWindow(0,&r,"\p",true,i,(WindowPtr)-1,false,0);
  138.     else
  139.         w = NewWindow(0,&r,"\p",true,i,(WindowPtr)-1,false,0);
  140.     SetPort(w);
  141.  
  142.     r.right -= r.left;
  143.     r.bottom -= r.top;
  144.     r.left = r.top = 0;
  145.  
  146.     updateRect = r;
  147.     updateRect.bottom -= 2*kButtonWindowMargin + kButtonHeight;
  148.  
  149.     if((long)buttonList <= 0)
  150.         {
  151.         if(buttonList == kEasyDialogSaveDiscardCancel)
  152.             buttonList = &dSaveDiscardCancelButtonList;
  153.         else
  154.             {    
  155.             if(buttonList == kEasyDialogOkayCancel)
  156.                 {
  157.                 dOkayCancelButtonList.count = 2;
  158.                 dOkayCancelButtonList.defaultButton = 0;
  159.                 dOkayCancelButtonList.cancelButton = 1;
  160.                 }
  161.             else if(buttonList == kEasyDialogCancelOkay)
  162.                 {
  163.                 dOkayCancelButtonList.count = 2;
  164.                 dOkayCancelButtonList.defaultButton = 1;
  165.                 dOkayCancelButtonList.cancelButton = 1;
  166.                 }
  167.             else
  168.                 {
  169.                 dOkayCancelButtonList.count = 1;
  170.                 dOkayCancelButtonList.defaultButton = 0;
  171.                 dOkayCancelButtonList.cancelButton = -1;
  172.                 }
  173.             buttonList = &dOkayCancelButtonList;
  174.             }
  175.         }
  176.  
  177.     if(buttonList->defaultButton >= buttonList->count)
  178.         buttonList->defaultButton = -1;
  179.     if(buttonList->cancelButton >= buttonList->count)
  180.         buttonList->cancelButton = -1;
  181.             
  182.     TextFont(0);
  183.     TextSize(12);
  184.     biggestButton = 0;
  185.     for(i = 0; i<buttonList->count; i++)
  186.         {
  187.         x = StringWidth(buttonList->button[i].name);
  188.         if(x > biggestButton)
  189.             biggestButton = x;
  190.         }
  191.  
  192.     biggestButton += kButtonTextMargin;
  193.  
  194.     s.left = kButtonWindowMargin;
  195.     s.bottom = r.bottom - kButtonWindowMargin;
  196.     s.right = s.left + biggestButton;
  197.     s.top = s.bottom - kButtonHeight;
  198.  
  199.     biggestButton += kButtonWindowMargin;
  200.  
  201.     for(i = 0; i<buttonList->count; i++)
  202.         {
  203.         ch[i] = NewControl(w,&s,buttonList->button[i].name,true,0,0,1,pushButProc,i);
  204.         if(i == buttonList->defaultButton)
  205.             {
  206.             defaultButtonRect = s;
  207.             InsetRect(&defaultButtonRect,-4,-4);
  208.             }
  209.         OffsetRect(&s,biggestButton,0);
  210.         }
  211.  
  212.     done = false;
  213.  
  214.     while(!done)
  215.         {
  216.         if(eventCount ++ & 1)
  217.             {
  218.             if(idleProc)
  219.                 (*idleProc)(refcon);
  220.             IdleWindow(-1);
  221.             }
  222.  
  223.         WaitNextEvent(0xffff,&er,0,nil);
  224.  
  225.         switch (er.what)
  226.             {
  227.             case 0:
  228.                 break;
  229.  
  230.             case mouseDown:
  231.                     {
  232.                     WindowPtr clickWindow;
  233.                     short part;
  234.                     ControlHandle whichControl;
  235.  
  236.                     part = FindWindow (er.where, &clickWindow);
  237.                     if(part == inMenuBar)
  238.                         {
  239.                         long p;
  240.  
  241.                         p = MenuSelect(er.where);
  242.                         }
  243.                     else if(part == inDrag
  244.                             && (clickWindow == w || er.modifiers & cmdKey))
  245.                         DragWindow(clickWindow,er.where,&gBigRect);
  246.                     else if(part != inContent || clickWindow != w)
  247.                         SysBeep(1);
  248.                     else
  249.                         {
  250.                         GlobalToLocal(&er.where);
  251.                         FindControl(er.where,w,&whichControl);
  252.                         if(whichControl)
  253.                             {
  254.                             if(TrackControl(whichControl,er.where,nil))
  255.                                 {
  256.                                 done = true;
  257.                                 result = GetCRefCon(whichControl);
  258.                                 }
  259.                             }
  260.                         }
  261.                     }
  262.                 break;
  263.  
  264.             case activateEvt:
  265.             activateEvent:
  266.                 HandleActivateEvent(&er);
  267.                 InitCursor();
  268.                 break;
  269.  
  270.             case updateEvt:
  271.                 if(er.message != (long)w)
  272.                     {
  273.                     HandleUpdateEvent(&er);
  274.                     SetPort(w);
  275.                     }
  276.                 else
  277.                     {
  278.                     BeginUpdate(w);
  279.                     DrawControls(w);
  280.                     if(buttonList->defaultButton >= 0)
  281.                         {
  282.                         PenSize(3,3);
  283.                         FrameRoundRect(&defaultButtonRect,16,16);
  284.                         PenNormal();
  285.                         }
  286.                     PenPat(qd.gray);
  287.                     MoveTo(updateRect.left + kButtonWindowMargin,updateRect.bottom);
  288.                     LineTo(updateRect.right - kButtonWindowMargin,updateRect.bottom);
  289.                     PenNormal();
  290.                     if(updateProc)
  291.                         (*updateProc)(refcon,&updateRect);
  292.                     EndUpdate(w);
  293.                     }
  294.                 break;
  295.  
  296.             case keyDown:
  297.                     {
  298.                     er.message &= 0x000000ff;
  299.                     if( (er.message == 13 || er.message == 3)
  300.                             && buttonList->defaultButton >= 0)        /* enter or return */
  301.                         {
  302.                         BlinkButton(ch[buttonList->defaultButton]);
  303.                         done = true;
  304.                         result = buttonList->defaultButton;
  305.                         }
  306.                     else if( ((er.message == '.' && (er.modifiers & cmdKey)) || er.message == 27)
  307.                             && buttonList->cancelButton >= 0)        /* esc or cmd-. */
  308.                         {
  309.                         BlinkButton(ch[buttonList->cancelButton]);
  310.                         done = true;
  311.                         result = buttonList->cancelButton;
  312.                         }
  313.                     else if (er.modifiers & cmdKey)                    /* a key-equiv? */
  314.                         {
  315.                         short capKey;
  316.  
  317.                         capKey = er.message;
  318.                         if(capKey >= 'a' && capKey <= 'z')
  319.                             capKey += 'A' - 'a';
  320.                         for(i = 0; i < buttonList->count; i++)
  321.                             if(capKey == buttonList->button[i].key)
  322.                                 {
  323.                                 BlinkButton(ch[i]);
  324.                                 done = true;
  325.                                 result = i;
  326.                                 }
  327.                             }
  328.                         }
  329.  
  330.                     if(!done)        /* someone snatch the key? */
  331.                         if(keyProc)
  332.                             (*keyProc)(refcon,er.message,er.modifiers);
  333.  
  334.  
  335.                 break;
  336.  
  337.             case kOSEvent:
  338.                 if( (er.message>>24) == kSuspendResumeMessage)
  339.                     goto activateEvent;
  340.                 break;
  341.     
  342.             } /* switch */
  343.         } /* while !done */
  344.  
  345.     DisposeWindow(w);
  346.  
  347.     EnableAllMenus(saveMenus);
  348.  
  349.     return result;
  350.     }
  351.  
  352. short EasyDialogMessage(short iconID,
  353.         StringPtr header,StringPtr body,
  354.         EasyDialogButtonList *buttonList)
  355.     {
  356.     EasyDialogMessageStuff stuff;
  357.     Rect r;
  358.     short result;
  359.  
  360.     stuff.header = header;
  361.     stuff.body = body;
  362.     stuff.iconID = iconID;
  363.  
  364.     r.left = r.top = 0;
  365.     r.right = 420;
  366.     r.bottom = 170;
  367.  
  368.     result = EasyDialog(&r,EasyDialogMessageUpdateProc,nil,nil,nil,buttonList,(long)&stuff);
  369.  
  370.     return result;
  371.     }
  372.  
  373. void EasyDialogMessageUpdateProc(long refcon,const Rect *updateRect)
  374.     {
  375.     EasyDialogMessageStuff *stuff;
  376.     Rect r;
  377.     Handle theIcon;
  378.  
  379.     stuff = (EasyDialogMessageStuff *) refcon;
  380.  
  381.     r.left = r.top = kButtonWindowMargin;
  382.     r.bottom = r.top + 32;
  383.  
  384.     if(stuff->iconID != -1)
  385.         {
  386.         r.right = r.left + 32;
  387.         r.top = kButtonWindowMargin;
  388.         theIcon = GetIcon(stuff->iconID);
  389.         if(theIcon)
  390.             {
  391.             PlotIcon(&r,theIcon);
  392.             ReleaseResource(theIcon);
  393.             }
  394.         else
  395.             PlotIconID(&r,atAbsoluteCenter,0,stuff->iconID);
  396.         }
  397.  
  398.     r.left += 32 + kButtonWindowMargin;
  399.     r.right = updateRect->right - kButtonWindowMargin;
  400.  
  401.     if(stuff->header)
  402.         TextBox(stuff->header+1,stuff->header[0],&r,teJustLeft);
  403.  
  404.     r.top = r.bottom + kButtonWindowMargin;
  405.     r.left = kButtonWindowMargin;
  406.     r.bottom = updateRect->bottom - kButtonWindowMargin;
  407.  
  408.     if(stuff->body)
  409.         TextBox(stuff->body+1,stuff->body[0],&r,teJustLeft);
  410.     }
  411.  
  412.  
  413. void BlinkButton(ControlHandle buttonControl)
  414.     {
  415.     long dummy;
  416.  
  417.     HiliteControl(buttonControl,1);
  418.     Delay(7,&dummy);
  419.     HiliteControl(buttonControl,0);
  420.     }
  421.  
  422.  
  423.  
  424.  
  425.  
  426. Boolean EasyDialogGetString(const StringPtr dialogTitle,
  427.         const StringPtr dialogPrompt,
  428.         StringPtr inOutString,short maxInOutStringLength)
  429. /*
  430.  * The scary thing about this routine is that
  431.  * it requires two resources: DLOG 128 and 129.
  432.  * 128 should use a modal alert-type window,
  433.  * and 129, a moveable-modal.
  434.  *
  435.  * The items should be:
  436.  *        1 - Okay
  437.  *        2 - Cancel
  438.  *        3 - Title static text = "^0"
  439.  *        4 - Prompt static text = "^1"
  440.  *        5 - Edit text field for entry
  441.  */
  442.     {
  443.     DialogPtr dp;
  444.     short hit;
  445.     short itemType;
  446.     Rect itemRect;
  447.     Handle itemHandle;
  448.     Boolean result;
  449.     Str255 outString;
  450.  
  451.     ParamText(dialogTitle,dialogPrompt,0,0);
  452.  
  453.     dp = GetNewDialog(128,0,(WindowPtr)-1);            //!!! should have two kinds
  454.     GetDItem(dp,5,&itemType,&itemHandle,&itemRect);
  455.     SetIText(itemHandle,inOutString);
  456.     SelIText(dp,5,0,32767);
  457.     ModalDialog(MyModalFilterProc,&hit);
  458.     (0,&hit);
  459.  
  460.     if(hit == 1)        /* Okay */
  461.         {
  462.         GetIText(itemHandle,outString);
  463.         if(outString[0] > maxInOutStringLength)
  464.             outString[0] = maxInOutStringLength;
  465.         BlockMove(outString,inOutString,maxInOutStringLength+1);
  466.         result = true;
  467.         }
  468.     else
  469.         result = false;
  470.     DisposeDialog(dp);
  471.  
  472.     return result;
  473.     }
  474.  
  475.  
  476. void BlinkItem(DialogPtr theDialog,short item)
  477.     {
  478.     ControlHandle button;
  479.     short itemType;
  480.     Rect itemRect;
  481.  
  482.     GetDItem(theDialog,item,&itemType,(void *)&button,&itemRect);
  483.     BlinkButton(button);
  484.     }
  485.  
  486.  
  487. pascal Boolean MyModalFilterProc(DialogPtr theDialog,
  488.         EventRecord *theEvent,short *itemHit)
  489.     {
  490.     short key;
  491.     Boolean result;
  492.     short itemType;
  493.     Rect itemRect;
  494.     Handle itemHandle;
  495.     short bump;
  496.     Str255 str;
  497.     long x;
  498.  
  499.     result = false;
  500.     switch(theEvent->what)
  501.         {
  502.         case keyDown:
  503.         case autoKey:
  504.             key = theEvent->message & 0xFF;
  505.             if(key == 27 || (key == '.' && (theEvent->modifiers & cmdKey)))
  506.                 {
  507.                 result = true;
  508.                 *itemHit = 2;
  509.                 BlinkItem(theDialog,2);
  510.                 }
  511.             else if(key == 3 || key == 13)
  512.                 {
  513.                 result = true;
  514.                 *itemHit = 1;
  515.                 BlinkItem(theDialog,1);
  516.                 }
  517.             else if((key =='a' || key == 'A') && (theEvent->modifiers &cmdKey))
  518.                 {
  519.                 SelIText(theDialog,5,0,32767);
  520.                 theEvent->what = 0;
  521.                 }
  522.             else if(gNumbers && (key == '+' || key == '='))
  523.                 {
  524.                 bump = 1;
  525.  
  526.         bumpString:
  527.                 if(theEvent->modifiers & shiftKey)
  528.                     bump *= 10;
  529.  
  530.                 GetDItem(theDialog,5,&itemType,&itemHandle,&itemRect);
  531.                 GetIText(itemHandle,str);
  532.                 StringToNum(str,&x);
  533.                 x += bump;
  534.                 NumToString(x,str);
  535.                 SetIText(itemHandle,str);
  536.                 SelIText(theDialog,5,0,32767);
  537.                 theEvent->what = 0;
  538.                 }
  539.             else if(gNumbers && (key == '-' || key == '_'))
  540.                 {
  541.                 bump = -1;
  542.                 goto bumpString;
  543.                 }
  544.             break;
  545.  
  546.         case updateEvt:
  547.             if(theEvent->message != (long)theDialog)
  548.                 HandleUpdateEvent(theEvent);
  549.             else
  550.                 {
  551.                 GrafPort *oldPort;
  552.                 GetPort(&oldPort);
  553.                 SetPort(theDialog);
  554.                 GetDItem(theDialog,1,&itemType,&itemHandle,&itemRect);
  555.                 InsetRect(&itemRect,-4,-4);
  556.                 PenSize(3,3);
  557.                 FrameRoundRect(&itemRect,16,16);
  558.                 PenNormal();
  559.                 SetPort(oldPort);
  560.                 }
  561.             break;
  562.  
  563.         case mouseDown:
  564.                 {
  565.                 WindowPtr clickWindow;
  566.                 short part;
  567.                 
  568.                 part = FindWindow (theEvent->where, &clickWindow);
  569.                 if(part == inDrag
  570.                         && (clickWindow == theDialog || theEvent->modifiers & cmdKey))
  571.                     {
  572.                     theEvent->what = 0;
  573.                     DragWindow(clickWindow,theEvent->where,&gBigRect);
  574.                     }
  575.                 }
  576.             break;
  577.         }
  578.  
  579. goHome:
  580.     return result;
  581.     }
  582.  
  583.  
  584. Boolean EasyDialogGetNumber(const StringPtr dialogTitle,
  585.         const StringPtr dialogPrompt,
  586.         long *inOutNumber)
  587.     {
  588.     Str255 numString;
  589.     Boolean result;
  590.  
  591.     NumToString(*inOutNumber,numString);
  592.  
  593.     gNumbers = true;
  594.     result = EasyDialogGetString(dialogTitle,dialogPrompt,numString,31);
  595.     gNumbers = false;
  596.  
  597.     if(result)
  598.         StringToNum(numString,inOutNumber);
  599.     return result;
  600.     }
  601.